package com.yneusoft.manage.service;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yneusoft.common.model.ResponseWrapper;
import com.yneusoft.common.tool.CommonTool;
import com.yneusoft.dao.entity.Book;
import com.yneusoft.dao.entity.BookType;
import com.yneusoft.dao.mapper.BookMapper;
import com.yneusoft.dao.mapper.BookTypeMapper;
import com.yneusoft.manage.mapper.ClassificationManageMapper;
import com.yneusoft.manage.model.*;
import com.yneusoft.manage.model.param.CheckFatherClassificationParam;
import com.yneusoft.manage.model.param.SaveClassificationParam;
import com.yneusoft.manage.model.param.SearchClassificationParam;
import com.yneusoft.manage.model.param.DeleteClassificationParam;
import com.yneusoft.manage.model.result.CheckFatherClassificationResult;
import com.yneusoft.manage.model.result.GetClassificationInfoResult;
import com.yneusoft.manage.model.result.GetClassificationListResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.yneusoft.common.enums.ResultEnum;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @author lt
 * @date 2021/10/20 19:05
 * @description:
 */
@Service
public class ClassificationManageService {

    @Autowired
    private BookTypeMapper bookTypeMapper;

    @Autowired
    private BookMapper bookMapper;

    @Autowired
    private ClassificationManageMapper classificationManageMapper;

    /**
     * 1. 获取分类列表
     *  当没有搜索关键字时，查询所有的根节点数据，并将其子节点放入其中，返回
     *  有搜索关键字时，查询与搜索关键字相关的内容，返回；
     * @param param 请求参数
     * @return 结点树
     */
    public ResponseWrapper getClassificationList(SearchClassificationParam param) {
        List<Map<String,Object>> childrenMap = null;
        if(StringUtils.isNotBlank(param.getSearchKey())){
            param.setSearchKey("%"+param.getSearchKey()+"%");
        }
        else{
            childrenMap = classificationManageMapper.getAllmap();
        }
        //取得判断是否有子类的 BookTypeList
        List<BookType> alltype = bookTypeMapper.selectList(null);
        //取得判断类型占有的 BookList
        List<Book> bookList = bookMapper.selectList(null);
        Page<Map<String,Object>> mapPage = classificationManageMapper.getClassificationList(new Page<>(param.getPage(), param.getPageSize()),param.getSearchKey());
        List<Map<String,Object>> queryList = mapPage.getRecords();

        //子类以及类型占有 判断
        List<Map<String,Object>> secondMaps = new ArrayList<>();
        for(Map<String,Object> map :queryList){
            for(BookType type :alltype) {
                if (map.get("aid") == type.getFatherAid()){
                    map.remove("isDelete");
                    map.put("isDelete",false);
                    break;
                }
            }
            for(Book book :bookList){
                if(map.get("aid") == book.getTypeAid()){
                    map.remove("isDelete");
                    map.put("isDelete",false);
                    break;
                }
            }
            secondMaps.add(map);
        }

        //如果searchKey为空，为根结点添加上子节点
        List<Map<String,Object>> result;
        if(!StringUtils.isNotBlank(param.getSearchKey())){
            //子节点子类以及类型占有 判断
            List<Map<String,Object>> secondChildrenMaps = new ArrayList<>();
            assert childrenMap != null;
            for(Map<String,Object> map :childrenMap){
                for(BookType type :alltype) {
                    if (map.get("aid") == type.getFatherAid()){
                        map.remove("isDelete");
                        map.put("isDelete",false);
                        break;
                    }
                }
                for(Book book :bookList){
                    if(map.get("aid") == book.getTypeAid()){
                        map.remove("isDelete");
                        map.put("isDelete",false);
                        break;
                    }
                }
                secondChildrenMaps.add(map);
            }
            Map<String,Object> map ;
            List<ClassificationListItemModel> classificationList = CommonTool.mapListToBeanList(secondMaps, ClassificationListItemModel.class);
            List<ClassificationListItemModel> childrenList = CommonTool.mapListToBeanList(secondChildrenMaps, ClassificationListItemModel.class);
            result = new ArrayList<>();
            for (ClassificationListItemModel item: classificationList){
                map = new HashMap<>();
                map.put("aid",item.getAid());
                map.put("name",item.getName());
                map.put("isDelete",item.getIsDelete());
                this.getChildrenTree1(map,childrenList);
                result.add(map);
            }
        }
        else{
            result = secondMaps;
        }
        List<ClassificationTreeNodeModel> listResults = CommonTool.mapListToBeanList(result, ClassificationTreeNodeModel.class);
        clearNullChildren(listResults);
        GetClassificationListResult classificationListResult = new GetClassificationListResult();
        classificationListResult.setRowNumber((int) mapPage.getTotal());
        classificationListResult.setList(listResults);
        return ResponseWrapper.markSuccess(classificationListResult);

    }

    /**
     * 2.删除分类
     * 根据传回的aid 删除分类
     * @param param DeleteClassificationParam
     * @return null
     */
    @Transactional
    public ResponseWrapper delClassification(DeleteClassificationParam param) {
        try {
            bookTypeMapper.deleteById(param.getAid());
            return ResponseWrapper.markSuccess();
        } catch (Exception e) {
            return ResponseWrapper.markError(ResultEnum.DATABASE_ERROR);
        }
    }

    /**
     * 3.【新增/修改】获取分类信息
     *
     * @param aid 类型aid
     * @return 类型名称，父级类型名称
     */
    public ResponseWrapper getClassificationInfo(Integer aid) {
        Map<String, Object> map = classificationManageMapper.getclassificationInfo(aid);
        GetClassificationInfoResult result = BeanUtil.toBean(map, GetClassificationInfoResult.class);
        return ResponseWrapper.markSuccess(result);
    }

    /**
     * 4.【新增/修改】获取类型列表
     * @return 所有类型的树
     */
    public ResponseWrapper getTypeList() {
        List<Map<String, Object>> mapList = bookTypeMapper.selectMaps(null);
        List<ClassificationModel> typeList = CommonTool.mapListToBeanList(mapList, ClassificationModel.class);
        Map<String,Object> map ;
        List<Map<String,Object>> result = new ArrayList<>();
        for (ClassificationModel item: typeList){
            if(item.getFatherAid() == null){
                map = new HashMap<>();
                map.put("aid",item.getAid());
                map.put("name",item.getName());
                this.getChildrenTree2(map,typeList);
                result.add(map);
            }
        }
        List<TypeTreeNodeModel> listResults = CommonTool.mapListToBeanList(result, TypeTreeNodeModel.class);
        return ResponseWrapper.markSuccess(listResults);
    }

    /**
     * 5.【新增/修改】校验父类是否为其子孙分类
     *
     * @return null
     */
    public ResponseWrapper checkFatherClassification(CheckFatherClassificationParam param) {
        CheckFatherClassificationResult result = new CheckFatherClassificationResult();
        if (param.getAid() == -1) {
            //新增分类没有限制
            result.setIsDescendant(false);
            return ResponseWrapper.markSuccess(result);
        }
        if(param.getAid().equals(param.getFatherAid())){
            //自己不可作为自己的父级
            result.setIsDescendant(true);
            return ResponseWrapper.markSuccess(result);
        }
        LambdaQueryWrapper<BookType> wrapper = new LambdaQueryWrapper<>();
        List<Map<String, Object>> mapList = bookTypeMapper.selectMaps(wrapper);
        List<ClassificationModel> typeList = CommonTool.mapListToBeanList(mapList, ClassificationModel.class);
        typeList = typeList.stream().peek(type -> {
            if (type.getFatherAid() == null) {
                type.setFatherAid(0);
            }
        }).collect(Collectors.toList());
        try {
            boolean flag = checkFatherClassification(param.getAid(), param.getFatherAid(), typeList);
            result.setIsDescendant(flag);
        } catch (RuntimeException e) {
            //递归函数中查询到存在子孙类时抛出异常，在这里接收到；
            result.setIsDescendant(true);
        }
        return ResponseWrapper.markSuccess(result);
    }

    /**
     * 6.【新增/修改】保存分类
     *
     * @param param 请求参数
     * @return null
     */
    @Transactional
    public ResponseWrapper saveClassification(SaveClassificationParam param) {
        BookType bookType = new BookType();
        List<Map<String, Object>> bookTypeMaps = bookTypeMapper.selectMaps(null);
        List<ClassificationModel> bookTypeList = CommonTool.mapListToBeanList(bookTypeMaps,ClassificationModel.class);
        //调用自定义方法获取level
        bookType.setLevel(getlevel(0, param.getFatherAid(), bookTypeList));
        bookType.setFatherAid(param.getFatherAid());
        bookType.setName(param.getName());
        LambdaUpdateWrapper<BookType> updateWrapper = new LambdaUpdateWrapper<>();
        //当没有父级类型时设值为null;
        updateWrapper.set(param.getFatherAid() == null, BookType::getFatherAid, null);
        try {
            //aid为-1时新增，其余为修改
            if (param.getAid() == -1) {
                bookTypeMapper.insert(bookType);
            } else {
                updateWrapper.eq(BookType::getAid, param.getAid());
                bookTypeMapper.update(bookType, updateWrapper);
            }
            return ResponseWrapper.markSuccess();
        } catch (Exception e) {
            return ResponseWrapper.markError(ResultEnum.DATABASE_RECORD_EXIST);
        }
    }


    /**
     * 获取类型的level 方法
     *
     * @param level 顶级类型的level
     * @param pId   父级类型aid
     * @param types 类型数组
     * @return 该类型的level
     */
    public Integer getlevel(Integer level, Integer pId, List<ClassificationModel> types) {
        if (pId == null) {
            return 0;
        }
        for (ClassificationModel type : types) {
            Integer parentAid = type.getAid(); //父级类型的aid
            if (parentAid.equals(pId)) {
                level++;
                Integer parentPId = type.getFatherAid(); //父级类型的fatherAid
                if (parentPId != null) {
                    return getlevel(level, parentPId, types);
                } else {
                    return level;
                }
            }
        }
        return level;
    }

    /**
     * 检查分类的父级类型aid 是否是该类型的子类
     *
     * @param aid   类型的aid
     * @param pId   父级类型aid
     * @param types 图书类型list
     * @return boolean
     */
    public boolean checkFatherClassification(Integer aid, Integer pId, List<ClassificationModel> types) {
        //获取子类
        List<ClassificationModel> children = types.stream().filter(x -> x.getFatherAid().equals(aid)).collect(Collectors.toList());
        //获取非子类
        List<ClassificationModel> successor = types.stream().filter(x -> !x.getFatherAid().equals(aid)).collect(Collectors.toList());
        //检查子类的aid
        for (ClassificationModel type : children) {
            if (type.getAid().equals(pId)) {
                throw new RuntimeException();
            } else {
                //获取子类的子类进行检查
                checkFatherClassification(type.getAid(), pId, successor);
            }
        }
        return false;
    }

    /**
     * 1.2获取分类列表 构建子节点树
     * @param map 父节点
     * @param list 类型列表
     */
    private void getChildrenTree1(Map<String, Object> map, List<ClassificationListItemModel> list) {
        List<Map<String, Object>> sonList = new ArrayList<>();
        Map<String, Object> childMap;
        for (ClassificationListItemModel item : list) {
            if (map.get("aid")==item.getFatherAid()) {
                childMap = new HashMap<>();
                childMap.put("aid", item.getAid());
                childMap.put("name", item.getName());
                childMap.put("isDelete",item.getIsDelete());
                sonList.add(childMap);
                this.getChildrenTree1(childMap, list);
            }
        }
        map.put("children", sonList);
    }

    /**
     * 4.2获取类型列表 构建子节点树
     * @param map 父节点
     * @param list 类型列表
     */
    private void getChildrenTree2(Map<String, Object> map, List<ClassificationModel> list) {
        List<Map<String, Object>> sonList = new ArrayList<>();
        Map<String, Object> childMap;
        for (ClassificationModel item : list) {
            if (map.get("aid")==item.getFatherAid()) {
                childMap = new HashMap<>();
                childMap.put("aid", item.getAid());
                childMap.put("name", item.getName());
                sonList.add(childMap);
                this.getChildrenTree2(childMap, list);
            }
        }
        map.put("children", sonList);
    }

    private void clearNullChildren(List<ClassificationTreeNodeModel> list){
        for(ClassificationTreeNodeModel node :list){
            List<ClassificationTreeNodeModel> children = node.getChildren();
            if( CollectionUtils.isNotEmpty(children)){
                clearNullChildren(children);
            }
            else{
                node.setChildren(null);
            }
        }
    }

}
